package com.lizemin.mybatis.sqlHandler;

import cn.hutool.core.util.StrUtil;
import com.lizemin.mybatis.entity.InsertSql;
import com.lizemin.mybatis.entity.MapperSql;
import com.lizemin.mybatis.entity.ParamValue;
import com.lizemin.mybatis.util.SqlUtil;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;

/**
 * @author lzm
 * @date 2025/5/20 22:10
 * @description
 */
public class InsertSqlHandler extends SqlHandler {

    public InsertSqlHandler(DataSource dataSource) {
        super(dataSource);
    }

    @Override
    public Object handle(MapperSql mapperSql, HashMap<String, ParamValue> paramValueMap, Class<?> returnType) {
        InsertSql insertSql = (InsertSql) mapperSql;
        if (paramValueMap.isEmpty()) {
            throw new RuntimeException("参数不能为空");
        }
        String sql = insertSql.getSql();
        List<String> placeholders = SqlUtil.getPlaceholders(sql);
        sql = sql.replaceAll("#\\{[^}]+}", "?");
        boolean useGeneratedKeys = insertSql.isUseGeneratedKeys();
        if (useGeneratedKeys) {
            try (Connection conn = dataSource.getConnection();
                 PreparedStatement pstmt = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS)) {
                String keyPropertyObjName = "";
                for (int i = 0; i < placeholders.size(); i++) {
                    String placeholder = placeholders.get(i);
                    if (placeholder.contains(".")) {
                        String[] strArr = placeholder.split("\\.");
                        String paramName = strArr[0];
                        String paramFieldName = strArr[1];
                        keyPropertyObjName = paramName;
                        ParamValue paramValue = paramValueMap.get(paramName);
                        Object obj = paramValue.getValue();
                        Field filed = paramValue.getType().getDeclaredField(paramFieldName);
                        filed.setAccessible(true);
                        Object value = filed.get(obj);
                        Class<?> type = filed.getType();
                        if (type.equals(String.class)) {
                            pstmt.setString(i + 1, (String) value);
                        } else if (type.equals(Integer.class) || type.equals(int.class)) {
                            pstmt.setInt(i + 1, (int) value);
                        } else if (type.equals(Long.class) || type.equals(long.class)) {
                            pstmt.setLong(i + 1, (long) value);
                        }
                    } else {
                        ParamValue paramValue = paramValueMap.get(placeholder);
                        Class<?> type = paramValue.getType();
                        if (type.equals(String.class)) {
                            pstmt.setString(i + 1, (String) paramValue.getValue());
                        } else if (type.equals(Integer.class) || type.equals(int.class)) {
                            pstmt.setInt(i + 1, (int) paramValue.getValue());
                        } else if (type.equals(Long.class) || type.equals(long.class)) {
                            pstmt.setLong(i + 1, (long) paramValue.getValue());
                        }
                    }
                }
                int rows = pstmt.executeUpdate();
                if (rows > 0) {
                    try (ResultSet generatedKeys = pstmt.getGeneratedKeys()) {
                        if (generatedKeys.next()) {
                            int generatedId = generatedKeys.getInt(1);
                            String keyProperty = insertSql.getKeyProperty();
                            if (StrUtil.isNotBlank(keyProperty)) {
                                if (StrUtil.isNotBlank(keyPropertyObjName)) {
                                    ParamValue paramValue = paramValueMap.get(keyPropertyObjName);
                                    Object obj = paramValue.getValue();
                                    Field keyFiled = paramValue.getType().getDeclaredField(keyProperty);
                                    keyFiled.setAccessible(true);
                                    keyFiled.set(obj, generatedId);
                                }
                            }
                            System.out.println("新插入数据的主键 ID 为: " + generatedId);
                        } else {
                            throw new RuntimeException("未获取到生成的主键 ID");
                        }
                    }
                }

                if (returnType.equals(Integer.class) || returnType.equals(int.class)) {
                    return rows;
                }
                if (returnType.equals(long.class) || returnType.equals(Long.class)) {
                    return (long) rows;
                }
            } catch (SQLException | NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            try (Connection conn = dataSource.getConnection();
                 PreparedStatement pstmt = conn.prepareStatement(sql)) {
                pstmt.setString(1, "唐僧2");
                int rows = pstmt.executeUpdate();
                if (returnType.equals(Integer.class) || returnType.equals(int.class)) {
                    return rows;
                }
                if (returnType.equals(long.class) || returnType.equals(Long.class)) {
                    return (long) rows;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return null;
    }
}
